﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using RainEngine.Controllers;
using RainEngine.SceneManagement;
using Microsoft.Xna.Framework.Graphics;

namespace RainEngine.SceneNodes
{
    /// <summary>
    /// 照相机类型
    /// </summary>
    public enum CameraType
    {
        ThirdPersonFar,
        ThirdPersonClose,
        HighView
    }

    public class ChaseCameraSceneNode : CameraSceneNode
    {
        /// <summary>
        /// 要跟踪的对象
        /// </summary>
        Renderable3DSceneNode node;

        /// <summary>
        /// 跟踪相机类型枚举
        /// </summary>
        public CameraType currentCameraType = CameraType.ThirdPersonFar;

        /// <summary>
        /// 相机位置偏离模型的距离。
        /// </summary>
        Vector3 CameraPositionOffset;

        /// <summary>
        /// 相机观察目标偏离的距离。
        /// </summary>
        Vector3 CameraTargetOffset;

        /// <summary>
        /// 创建一个跟随相机
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="setScene">所属场景</param>
        /// <param name="node">要跟踪的对象</param>
        public ChaseCameraSceneNode(GraphicsDevice graphicsDevice, Scene setScene, Renderable3DSceneNode node)
            : base(graphicsDevice, setScene, Vector3.Zero, Vector3.Forward)
        {
            this.node = node;
        }

        /// <summary>
        /// 更新视矩阵
        /// </summary>
        /// <param name="updateProjection">是否更新投影矩阵</param>
        public override void UpdateViewMatrix(bool updateProjection)
        {
            if (Input.KeyboardKeyJustPressed(Keys.Tab))
            {
                currentCameraType += 1;
                if (currentCameraType > CameraType.HighView)
                    currentCameraType = CameraType.ThirdPersonFar;
            }

            Vector3 cameraRotatedPosition;
            Vector3 cameraFinalPosition;
            Vector3 cameraFinalTargetPosition;

            switch (currentCameraType)
            {
                case CameraType.ThirdPersonFar:
                    CameraPositionOffset = new Vector3(0, 15, -25);
                    CameraTargetOffset = new Vector3(0, 10, 0);
                    break;
                case CameraType.ThirdPersonClose:
                    CameraPositionOffset = new Vector3(0, 6, -9);
                    CameraTargetOffset = new Vector3(0, 6, 0);
                    break;
                case CameraType.HighView:
                    CameraPositionOffset = new Vector3(0, 40, -1);
                    CameraTargetOffset = new Vector3(0, 0, 0);
                    break;
                default:
                    throw new InvalidOperationException("照相机类型不存在");
            }

            cameraFinalTargetPosition = node.Pose.Position + CameraTargetOffset;
            cameraRotatedPosition = Vector3.Transform(CameraPositionOffset, Quaternion.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(-node.AngleRotation.Y)));
            cameraFinalPosition = node.Pose.Position + cameraRotatedPosition;

            viewMatrix = Matrix.CreateLookAt(cameraFinalPosition, cameraFinalTargetPosition, Vector3.Up);

            //updateProjection为true则重新设置真实投影矩阵和逻辑投影矩阵
            if (updateProjection)
            {
                //  真实视锥体，基于很大的真实远裁平面
                projectionMatrix = Matrix.CreatePerspectiveFieldOfView(cameraFov, AspectRatio, nearPlane, internalFarPlane);
                internalFarPlaneBoundingFrustum.Matrix = viewMatrix * projectionMatrix;

                //  基于逻辑远裁平面的逻辑视锥体。
                farPM = Matrix.CreatePerspectiveFieldOfView(cameraFov, AspectRatio, nearPlane, FarPlane);
                farPlaneBoundingFrustum.Matrix = viewMatrix * farPM;
            }
            hasChanged = true;
        }
    }
}
